package org.example.Servlet;

import com.alibaba.fastjson.JSON;
import javassist.*;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import org.apache.commons.beanutils.BeanUtils;
import org.example.com.Controller.UserController;
import org.example.com.Utils.ScanAllClassUtils;
import org.example.com.Utils.StringUtils;
import org.example.com.model.URLMapping;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @author cc
 * @date 2021/8/3 14:19
 * @Description
 */

public class DispatcherServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");
        try {
            URLMapping urlMapping = ScanAllClassUtils.getUrlMapping(req.getRequestURI());
            //判断urlMaping是否存在
            if (urlMapping==null){
                resp.setStatus(404);
                resp.getWriter().write("请求路径不存在：404" +" 路径为："+req.getRequestURI());
                return;
            }
            //获取类
            Object obj = urlMapping.getObj();
            //获取类对应的方法
            Method method = urlMapping.getMethod();
            //获取类里面参数的名称和类型
            Map<String, Class<?>> parameter = urlMapping.getParameter();

            //把这些全部封装到一个数组
            Object[] params = new Object[method.getParameterCount()];
            int index = 0;
            for (String key : parameter.keySet()) {
                //请求参数的名称
                 String paramsname = key;
                 //请求参数的类型
                 Class<?> paramType = parameter.get(paramsname);
                 if (paramType==HttpServletRequest.class){
                     params[index] = req;
                 }else if (paramType==HttpServletResponse.class){
                     params[index]=resp;
                 }else {
                     //获取请求参数的值 要考虑根据不同的参数类型进行数据转换
                     String name = req.getParameter(paramsname);
                     if (StringUtils.isEmpty(name)){
                         //除开res和resp，其他在括号内的参数。如String name ，int age;
                         //进行数据处理
                         if (paramType==String.class){
                             params[index] = name;
                         }else if (paramType==Byte.class){
                             params[index] = Byte.parseByte(name);
                         } else if (paramType==Short.class){
                             params[index] = Short.parseShort(name);
                         } else if (paramType==Long.class){
                             params[index] = Long.parseLong(name);
                         } else if (paramType==Integer.class){
                             params[index] = Integer.parseInt(name);
                         } else if (paramType==Double.class){
                             params[index] = Double.parseDouble(name);
                         }else if (paramType==Float.class){
                             params[index] = Float.parseFloat(name);
                         }else if (paramType ==Boolean.class){
                             params[index] = Boolean.parseBoolean(name);
                         }else if (paramType ==Character.class){
                             params[index] = name.toCharArray()[0];
                         }
                         else {
                             //不是基本类型
                             params[index] = null;
                         }
                     }
                     else {
                         //处理java 普通对象
                         Object paramObj = paramType.newInstance();
                         BeanUtils.populate(paramObj,req.getParameterMap());
                         params[index] = paramObj;
                     }
                 }
                 index++;
            }


            //淘汰方法
//            Object[] params = getObjectsAndParasm_Old(req, resp, method);


            //实现方法，并且根据反射的类是否有返回值 返回方法
            Object views = method.invoke(obj, params);
            if (views!=null){
                if (views instanceof String){
                    String viewname = views.toString();
                    //如果有该单词表示，要进行重定向
                    if (viewname.startsWith("redirect:")){
                        String contextPath = req.getContextPath();
                        System.out.println();
                        resp.sendRedirect(req.getContextPath() + viewname.replace("redirect:",""));
                    }//请求转发
                    else {
                        req.getRequestDispatcher("/WEB-INF/jsp/"+viewname+".jsp").forward(req,resp);
                    }
                    //返回值是去其他类型
                }else {
                    //将views转换成json对象
                    resp.setContentType("application/json:charset=UTF-8");
                    String toJSONString = JSON.toJSONString(views);
                    resp.getWriter().write(toJSONString);
                }
            }

        } catch (Exception e) {
            resp.setStatus(500);
            resp.getWriter().write("服务器内部错误");
            e.printStackTrace(resp.getWriter());//打印到服务器
            e.printStackTrace();//打印到控制台
        }
    }

    private Object[] getObjectsAndParasm_Old(HttpServletRequest req, HttpServletResponse resp, Method method) {
        //获取方法上()括号里参数的类型
        Class<?>[] parameterTypes = method.getParameterTypes();
        //（）里有多少个参数，生成相应的Object[]数组
        Object [] params = new Object[method.getParameterCount()];
        int index = 0;
        for (Class<?> parameterType : parameterTypes) {
            if (parameterType==HttpServletRequest.class){
                params[index] = req;
            }else if (parameterType==HttpServletResponse.class){
                params[index] =resp;
            }else {
                //获取到除了res和resp的参数名称
                //通过反射获取参数的类型
                params[index] = null;
            }
            index++;
        }
        return params;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
